package com.dukk.gis.tools.extensions.projections;

import com.dukk.gis.tools.GeoTool;
import com.jhlabs.map.proj.EquidistantAzimuthalProjection;
import org.locationtech.jts.geom.*;
import org.locationtech.spatial4j.distance.DistanceUtils;

import java.awt.geom.Point2D;

/**
 * 方位等距投影
 *
 * https://en.wikipedia.org/wiki/Azimuthal_equidistant_projection
 */
public class EquidistantAzimuthalProjectionTool {

    EquidistantAzimuthalProjection equidistantAzimuthalProjection = new EquidistantAzimuthalProjection();

    GeometryFactory geometryFactory = GeoTool.getGeoFactory();

    public Coordinate project(Coordinate coordinate){

        double lon = DistanceUtils.toRadians(coordinate.x);
        double lat = DistanceUtils.toRadians(coordinate.y);

        Point2D.Double xy = new Point2D.Double();
        equidistantAzimuthalProjection.project(lon, lat, xy);

        return new Coordinate(xy.x, xy.y);
    }

    public Coordinate inverseProject(Coordinate coordinate){

        Point2D.Double xy_inverse = new Point2D.Double();
        equidistantAzimuthalProjection.projectInverse(coordinate.x, coordinate.y, xy_inverse);

        double x = DistanceUtils.toDegrees(xy_inverse.x);
        double y = DistanceUtils.toDegrees(xy_inverse.y);

        return new Coordinate(x, y);
    }

    public Geometry project(LineString geometry){
        Coordinate coordinates[] = geometry.getCoordinates();
        CoordinateList coordinateList = new CoordinateList();
        for(Coordinate coordinate : coordinates){
            coordinateList.add(project(coordinate));
        }
        return geometryFactory.createLineString(coordinateList.toCoordinateArray());
    }

    public Geometry project(Polygon geometry){
        Coordinate coordinates[] = geometry.getCoordinates();
        CoordinateList coordinateList = new CoordinateList();
        for(Coordinate coordinate : coordinates){
            coordinateList.add(project(coordinate));
        }
        return geometryFactory.createPolygon(coordinateList.toCoordinateArray());
    }

    public Geometry inverseProject(LineString geometry){
        Coordinate coordinates[] = geometry.getCoordinates();
        CoordinateList coordinateList = new CoordinateList();
        for(Coordinate coordinate : coordinates){
            coordinateList.add(inverseProject(coordinate));
        }
        return geometryFactory.createLineString(coordinateList.toCoordinateArray());
    }

    public Geometry inverseProject(Polygon geometry){
        Coordinate coordinates[] = geometry.getCoordinates();
        CoordinateList coordinateList = new CoordinateList();
        for(Coordinate coordinate : coordinates){
            coordinateList.add(inverseProject(coordinate));
        }
        return geometryFactory.createPolygon(coordinateList.toCoordinateArray());
    }

}
